package com.zmn.oms.third.zhimi;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.oms.common.utils.HttpUtil;
import com.zmn.oms.third.base.dto.api.ApiInvokResult;
import com.zmn.oms.third.zhimi.api.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：智米API接口的封装工具类
 *
 * @author lhl
 * @date 2020/04/24 22:33
 */
@Slf4j
public final class ZhimiApiInvoker {

    /**
     * 拉取订单信息
     * @param appid 服务商编码
     * @return
     */
    public static ApiInvokResult<List<ZhimiOrderResp>> pullOrders(String appid) {
        String realAppid = Optional.ofNullable(appid).orElse(ZhimiConsts.APP_ID);
        String content = "name=" + realAppid;
        ApiInvokResult<String> response = apiInvok(ZhimiConsts.PATH_GET_ORDER, content);

        ApiInvokResult<List<ZhimiOrderResp>> result = new ApiInvokResult<>();
        result.setSuccess(response.isSuccess());
        result.setMsg(response.getMsg());
        // 将返回结果解析成订单数据
        if (response.isSuccess()) {
            ZhimiOrderResp zhimiOrderResp = new ZhimiOrderResp();

            String dataStr = response.getData();
            JSONArray dataArr = JSON.parseArray(dataStr);

            List<ZhimiOrderResp> orders = new LinkedList<>();

            if (dataArr != null) {
                for (int i=0,len=dataArr.size(); i<len; i++) {
                    String item = dataArr.getString(i);

                    ZhimiOrderResp order = JSON.parseObject(item, ZhimiOrderResp.class);
                    order.setMetadata(item);    // 保存原始json数据
                    orders.add(order);
                }
            }

            result.setData(orders);
        }

        return result;
    }

    /**
     * 同步订单信息
     * @param content
     * @return
     */
    public static ApiInvokResult syncOrderStatus(String content) {
        return apiInvok(ZhimiConsts.PATH_PUSH_STAUS, content);
    }

    /**
     * 同步订单信息
     * @param content
     * @param isAC 标识是否是空调订单
     * @return
     */
    public static ApiInvokResult syncOrderComplete(String content, boolean isAC) {
        String path = isAC ? ZhimiConsts.PATH_PUSH_COMPLETE_AC : ZhimiConsts.PATH_PUSH_COMPLETE;
        return apiInvok(path, content);
    }

    /**
     * 接单回调
     * @param content
     * @return
     */
    public static ApiInvokResult acceptOrderCallback(String content) {
        return apiInvok(ZhimiConsts.PATH_GET_ORDER_CALLBACK, content);
    }

    /**
     * SN码校验
     * @param outerId
     * @param sn
     * @return
     */
    public static ApiInvokResult<ZhimiSNCheckResp> checkSN(String outerId, String sn) {
        String content = String.format("{\"name\":\"%s\",\"sn\":\"%s\"}", outerId, sn);
        return apiInvok(ZhimiConsts.PATH_SN_CHECK, content, ZhimiSNCheckResp.class);
    }

    /**
     * 查询故障信息
     * @param productCode 智米物料编码
     * @return
     */
    public static ApiInvokResult<ZhimiFaultResp> queryFaults(String productCode) {
        String code = Optional.ofNullable(productCode).orElse("");
        String content = String.format("{\"productcode\":\"%s\"}", code);
        return apiInvok(ZhimiConsts.PATH_GET_FAULT, content, ZhimiFaultResp.class);
    }

    /**
     * 申请配件
     * @param content
     * @return
     */
    public static ApiInvokResult partApply(String content) {
        return apiInvok(ZhimiConsts.PATH_PART_APPLY, content);
    }

    /**
     * 查询故障配件
     * @param productCode 智米物料编码
     * @return
     */
    public static ApiInvokResult<ZhimiFaultPartResp> queryFaultParts(String productCode) {
        String code = Optional.ofNullable(productCode).orElse("");
        String content = String.format("{\"productcode\":\"%s\"}", code);
        return apiInvok(ZhimiConsts.PATH_GET_FAULT_PART, content, ZhimiFaultPartResp.class);
    }

    /**
     * 查询配件物流信息
     * @param outerId 智米服务单号
     * @return
     */
    public static ApiInvokResult<ZhimiExpressResp> queryPartExpress(String outerId) {
        String content = String.format("{\"name\":\"%s\"}", outerId);
        return apiInvok(ZhimiConsts.PATH_GET_PART_EXPRESS, content, ZhimiExpressResp.class);
    }

    /**
     * 调用api
     * @param path
     * @param content
     * @return
     */
    private static ApiInvokResult<String> apiInvok(String path, String content) {
        ApiInvokResult<String> result = new ApiInvokResult<>();
        result.setSuccess(false);

        try {
            String response = null;
            if (ZhimiConsts.PATH_GET_ORDER.equals(path)) {
                response = _doInvokUseHTTPGET(path, content);
            }
            else {
                response = _doInvok(path, content);
            }

            JSONObject jsonObj = JSON.parseObject(response);

            String message = jsonObj.getString("message");
            String status = jsonObj.getString("status");

            result.setMsg(message);
            result.setSuccess("0".equals(status));

            if (jsonObj.containsKey("data")) {
                String data = jsonObj.getString("data");
                result.setData(data);
            }

        } catch (Exception e) {
            result.setMsg(e.getMessage());

            log.info("【{}-API】 请求失败:[{}]", ZhimiConsts.CHANNEL_NAME, e.getMessage());
            log.error(e.getMessage(), e);
        }

        return result;
    }

    /**
     * 调用api
     * @param path
     * @param content
     * @param tClass
     * @param <T>
     * @return
     */
    private static <T> ApiInvokResult<T> apiInvok(String path, String content, Class<T> tClass) {
        ApiInvokResult<T> result = new ApiInvokResult<>();
        result.setSuccess(false);

        try {
            String response = _doInvok(path, content);

            JSONObject jsonObject = JSON.parseObject(response);

            String message = jsonObject.getString("message");
            result.setMsg(message);

            String status = jsonObject.getString("status");
            if ("0".equals(status)) {
                String dataStr = jsonObject.getString("data");
                T data = JSON.parseObject(dataStr, tClass);

                result.setSuccess(true);
                result.setData(data);
            }

        } catch (Exception e) {
            result.setMsg(e.getMessage());

            log.info("【{}-API】 请求失败:[{}]", ZhimiConsts.CHANNEL_NAME, e.getMessage());
            log.error(e.getMessage(), e);
        }

        return result;
    }

    /**
     * 调用api
     * @param path
     * @param content
     * @param typeReference
     * @param <T>
     * @return
     */
    private static <T> ApiInvokResult<T> apiInvok(String path, String content, TypeReference<T> typeReference) {
        ApiInvokResult<T> result = new ApiInvokResult<>();
        result.setSuccess(false);

        try {
            String response = _doInvok(path, content);

            JSONObject jsonObject = JSON.parseObject(response);

            String message = jsonObject.getString("message");
            result.setMsg(message);

            String status = jsonObject.getString("status");
            if ("0".equals(status)) {
                String dataStr = jsonObject.getString("data");
                T data = JSON.parseObject(dataStr, typeReference);

                result.setSuccess(true);
                result.setData(data);
            }

        } catch (Exception e) {
            result.setMsg(e.getMessage());

            log.info("【{}-API】 请求失败:[{}]", ZhimiConsts.CHANNEL_NAME, e.getMessage());
            log.error(e.getMessage(), e);
        }

        return result;
    }

    /**
     * 调用api
     * @param path
     * @param content
     * @return
     */
    private static String _doInvok(String path, String content) throws Exception{
        String url = ZhimiConsts.API_DOMAIN + path;

        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", _md5(ZhimiConsts.APPKEY));

        log.info("【{}-API】<API请求> Url:[{}] RequestBody:[{}]", ZhimiConsts.CHANNEL_NAME, url, content);
        String response = HttpUtil.httpPost(url, content, headers);
        log.info("【{}-API】<API响应> ResponseBody:[{}]", ZhimiConsts.CHANNEL_NAME, response);

        return response;
    }

    /**
     * 调用api
     * @param path
     * @param params
     * @return
     */
    private static String _doInvokUseHTTPGET(String path, String params) throws Exception{
        String url = ZhimiConsts.API_DOMAIN + path + "?" + params;

        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", _md5(ZhimiConsts.APPKEY));

        log.info("【{}-API】<API请求> Url:[{}]", ZhimiConsts.CHANNEL_NAME, url);
        String response = HttpUtil.doGet(url, headers);
        log.info("【{}-API】<API响应> ResponseBody:[{}]", ZhimiConsts.CHANNEL_NAME, response);

        return response;
    }


    /**
     * MD5
     * @param appkey
     * @return
     */
    private static String _md5(String appkey) {
        return String.format("basic %s", DigestUtils.md5Hex(appkey).toUpperCase());
    }

    /**
     * 私有构造器，防止外部实例化
     */
    private ZhimiApiInvoker() {}


    public static void main(String[] args) {
        ZhimiConsts.API_DOMAIN = "http://webapi.crm.zhimi.com";   // 线上地址
        //ZhimiConsts.API_DOMAIN = "http://120.131.15.144:8099";      // 测试地址
        ZhimiConsts.APP_ID = "1000063";
        ZhimiConsts.APPKEY = "y*t%#e&oygUxt8";
        ZhimiConsts.STORE_ID = "SFG1";

        String outerId = "FW200507000007";

        // 拉取订单
        /*ApiInvokResult<List<ZhimiOrderResp>> result = pullOrders(ZhimiConsts.APP_ID);
        List<ZhimiOrderResp> data = result.getData();*/
        // 校验SN
/*        ApiInvokResult<ZhimiSNCheckResp> result = checkSN("FW200507000007", "16182/00323045");
        ZhimiSNCheckResp resp = result.getData();*/

        // 获取故障配件信息
        /*ApiInvokResult<ZhimiFaultResp> result = queryFaults(null);
        ZhimiFaultResp data = result.getData();*/

        // 获取故障配件信息
        //ApiInvokResult<ZhimiFaultPartResp> result = queryFaultParts(ZhimiConsts.PRODUCT_LINE_CODE_LV3);
        /*ApiInvokResult<ZhimiFaultPartResp> result = queryFaultParts(null);
        ZhimiFaultPartResp data = result.getData();

        List<ZhimiFaultPartResp.FaultPart> collect = data.getLines().stream()
                .filter(item -> StringUtil.isNotBlank(item.getNouseproduct()))
                .collect(Collectors.toList());

        System.out.println(collect.size());*/

        // 获取物流信息
        ApiInvokResult<ZhimiExpressResp> result = queryPartExpress("FW200824000217");

        //testApplyParts();

        //testSyncMaster(outerId);

        // 同步取消
        //pushCancel();

        //String content = "{\"buydate\":\"2022-10-01 00:00:00\",\"faultLines\":[{\"faultcode\":\"M30UAJ0501\",\"faultname\":\"机械按键失效\"},{\"faultcode\":\"M30UAJ0502\",\"faultname\":\"机械按键手感差\"}],\"isexistcertificate\":true,\"name\":\"FW200609000122\",\"partlines\":[{\"oldpartcode\":\"E95TOS1901202S\",\"oldpartname\":\"智米智能马桶盖机头\",\"partcode\":\"E95TOS1901202S\",\"partname\":\"智米智能马桶盖机头\",\"qty\":1,\"newsn\":\"16182/000437342\",\"oldsn\":\"16182/00412620\"}],\"productcode\":\"E95TOS1901202S\",\"receivenumber\":\"SF1163286088683\",\"servicetype\":1,\"sn\":\"16182/00412620\",\"uploadpics\":\"https://img1.xiujiadian.com/prod/mapp/202007/20200717115953_347315.jpg,https://img1.xiujiadian.com/prod/mapp/202007/20200717115954_858678.jpg,https://img1.xiujiadian.com/prod/mapp/202007/20200717115955_856694.jpg,https://img1.xiujiadian.com/prod/mapp/202007/20200717115956_044714.jpg,https://img1.xiujiadian.com/prod/mapp/202007/20200717115957_357554.jpg,https://img1.xiujiadian.com/prod/mapp/202007/20200717120007_805281.jpg\",\"warranty\":1}";
        //syncOrderComplete(content, false);
    }


    private static void pushCancel() {
        List<String> list = new LinkedList<>();
        list.add("FW200515000592");


        String content = "{\"name\":\"%s\",\"servicetype\":99,\"reasontype\":19}";


        for (String item : list) {
            ApiInvokResult<String> stringApiInvokResult = apiInvok(ZhimiConsts.PATH_PUSH_COMPLETE, String.format(content, item));

            System.out.println("订单：["+ item +"] result="+ JSON.toJSONString(stringApiInvokResult));

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    private static void testSyncMaster(String outerId) {
        Date now = new Date();
        String opTimeStr = DateUtil.toString(now, DateUtil.FORMAT_DEFAULT);

        ZhimiSyncOrderStatusReq orderStatusReq = new ZhimiSyncOrderStatusReq();
        orderStatusReq.setName(outerId);
        orderStatusReq.setDealstatus(7); // 7：派工工程师
        orderStatusReq.setDealtime(opTimeStr);
        orderStatusReq.setRemark(String.format("工程师 测试111 已接单"));

        ZhimiSyncOrderStatusReq.DistributeOrder distributeOrder = orderStatusReq.new DistributeOrder();
        distributeOrder.setDispatchingtime(opTimeStr);
        distributeOrder.setWorkername("测试111");
        distributeOrder.setPhonenumber("15730252174");
        orderStatusReq.setJsondata(JSON.toJSONString(distributeOrder));

        String content = JSON.toJSONString(orderStatusReq);
        ApiInvokResult result = ZhimiApiInvoker.syncOrderStatus(content);
        System.out.println(JSON.toJSONString(result));
    }

    // 测试申请配件
    private static void testApplyParts() {
        String applyTime = DateUtil.dateFormatToString(new Date(), DateUtil.FORMAT_DEFAULT);
        ZhimiApplyPartsReq applyPartsReq = new ZhimiApplyPartsReq();
        applyPartsReq.setName("FW200508000007");
        applyPartsReq.setType(2);   // 类型固定填2
        applyPartsReq.setStationcode(ZhimiConsts.APP_ID);
        applyPartsReq.setStockcode(ZhimiConsts.STORE_ID);
        applyPartsReq.setSubmit_time(applyTime);
        applyPartsReq.setRecipient("九戒");
        applyPartsReq.setAddress("北京市朝阳区北土城西路元大都7号");
        applyPartsReq.setPhonenumber("18010491280");

        List<ZhimiApplyPartsReq.Part> applyParts = new LinkedList<>();
        ZhimiApplyPartsReq.Part part = new ZhimiApplyPartsReq.Part();
        part.setMaterialcode("E5020502300001");
        part.setQty(5);
        applyParts.add(part);
        ZhimiApplyPartsReq.Part part1 = new ZhimiApplyPartsReq.Part();
        part1.setMaterialcode("E5020121220002");
        part1.setQty(3);
        applyParts.add(part1);
        applyPartsReq.setDatalines(applyParts);

        ApiInvokResult result = ZhimiApiInvoker.partApply(JSON.toJSONString(applyPartsReq));
        System.out.println(JSON.toJSONString(result));
    }

    // 测试接单回调接口
    private static void testAcceptOrderCallback(String outerId) {
        String content = String.format("{\"srvname\":\"%s\",\"datalines\":[{\"name\":\"%s\"}]}", ZhimiConsts.APP_ID,
                outerId);

        ApiInvokResult result = ZhimiApiInvoker.acceptOrderCallback(content);
    }

    private static void testAcceptOrder(String outerId) {
        Date now = new Date();
        String opTimeStr = DateUtil.toString(now, DateUtil.FORMAT_DEFAULT);

        ZhimiSyncOrderStatusReq orderStatusReq = new ZhimiSyncOrderStatusReq();
        orderStatusReq.setName(outerId);
        orderStatusReq.setDealstatus(1); // 1：服务商接单
        orderStatusReq.setDealtime(opTimeStr);
        orderStatusReq.setRemark("接单成功");

        ZhimiSyncOrderStatusReq.AcceptOrder acceptOrder = orderStatusReq.new AcceptOrder();
        acceptOrder.setReceivetime(opTimeStr);
        orderStatusReq.setJsondata(JSON.toJSONString(acceptOrder));

        String content = JSON.toJSONString(orderStatusReq);
        ApiInvokResult result = ZhimiApiInvoker.syncOrderStatus(content);
        System.out.println(JSON.toJSONString(result));
    }

    private static void testSyncDutyTime(String outerId) {
        Date now = new Date();
        String opTimeStr = DateUtil.toString(now, DateUtil.FORMAT_DEFAULT);
        String dutytimeStr = "2020-05-15 09:00:00";

        ZhimiSyncOrderStatusReq orderStatusReq = new ZhimiSyncOrderStatusReq();
        orderStatusReq.setName(outerId);
        orderStatusReq.setDealstatus(14); // 14：预约成功
        orderStatusReq.setDealtime(opTimeStr);
        orderStatusReq.setRemark("预约成功");

        ZhimiSyncOrderStatusReq.DutyTime dutyTime = orderStatusReq.new DutyTime();
        dutyTime.setBooktime(dutytimeStr);
        dutyTime.setRemark("预约成功");
        orderStatusReq.setJsondata(JSON.toJSONString(dutyTime));

        String content = JSON.toJSONString(orderStatusReq);
        ApiInvokResult result = ZhimiApiInvoker.syncOrderStatus(content);
    }
}
